/**
 * Created on May 2, 2007
 */
package jvs.vfs.local;

import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.Arrays;
import java.util.Comparator;

import jvs.vfs.IFile;
import jvs.vfs.IFileBaseImpl;
import x.java.io.File;

/**
 * @author qiangli
 * 
 */
public class LocalFileImpl extends IFileBaseImpl {
	protected java.io.File file = null;

	public LocalFileImpl(URI uri) {
		super(uri);
		file = new java.io.File(uri);
		if (DEBUG) {
			debug(this, "uri: " +uri + " file: " + file);
		}
	}

	protected LocalFileImpl(java.io.File file) {
		super();
		this.file = file;
		this.uri = file.toURI();
		if (DEBUG) {
			debug(this, "file: " + file +" uri: " + uri);
		}
	}

	public boolean canRead() {
		return this.file.canRead();
	}

	public boolean canWrite() {
		return this.file.canWrite();
	}

	public boolean copy(URI uri) {
		java.io.InputStream in;
		try {
			in = new java.io.FileInputStream(this.file);
			OutputStream out = uri.toURL().openConnection().getOutputStream();
			byte buf[] = new byte[File.BUFSIZE];
			int len;
			while ((len = in.read(buf, 0, File.BUFSIZE)) != -1) {
				out.write(buf, 0, len);
			}
			in.close();
			out.close();
			return true;
		} catch (Exception e) {
			debug(e);
		}
		return false;
	}

	public boolean create() {
		try {
			return this.file.createNewFile();
		} catch (IOException e) {
			e.printStackTrace();
			debug(e);
		}
		return false;
	}

	private void debug(Exception e) {
		e.printStackTrace();
	}

	public boolean delete() {
		return this.file.delete();
	}

	public boolean exists() {
		return this.file.exists();
	}

	@Override
	public boolean isLocal() {
		return true;
	}

	@Override
	public boolean isNative() {
		return true;
	}

	public String getContent() {
		try {
			int size = (int) this.file.length();
			byte[] buf = new byte[size];
			java.io.InputStream is;
			is = new java.io.FileInputStream(this.file);
			java.io.BufferedInputStream bis = new java.io.BufferedInputStream(
					is, File.BUFSIZE);
			int read = 0;
			for (int i = 0; i < this.file.length(); i += read) {
				read = bis.read(buf, i, buf.length - i);
			}
			return new String(buf);
		} catch (Exception e) {
			debug(e);
		}
		return null;
	}

	public String getContentEncoding() {
		return super.getContentEncoding();
	}

	public String getContentType() {
		return super.getContentType();
	}

	public InputStream getInputStream() {
		try {
			return new java.io.FileInputStream(this.file);
		} catch (Exception e) {
			throw  new RuntimeException(e.getMessage()+": "+uri);
		}
	}

	public long getLastModified() {
		return this.file.lastModified();
	}

	public long getLength() {
		if (!this.file.exists()) {
			return -1;
		}
		return this.file.length();
	}

	public OutputStream getOutputStream() {
		try {
			return new java.io.FileOutputStream(this.file);
		} catch (Exception e) {
			debug(e);
		}
		return null;
	}

	public OutputStream getOutputStream(boolean append) {
		try {
			return new java.io.FileOutputStream(this.file, append);
		} catch (Exception e) {
			debug(e);
		}
		return null;
	}
	
	public boolean isDirectory() {
		return this.file.isDirectory();
	}

	public boolean isFile() {
		return this.file.isFile();
	}

	public String[] list() {
		return this.file.list();
	}

	@Override
	public IFile[] listFiles() {
		java.io.File[] files = this.file.listFiles();
		if (files == null) {
			return null;
		}
		IFile[] rl = new IFile[files.length];
		for (int i = 0; i < files.length; i++) {
			rl[i] = new LocalFileImpl(files[i]);
		}
		return rl;
	}

	@Override
	public IFile[] listFiles(int off, int max) {
		java.io.File[] files = this.file.listFiles();
		if (files == null) {
			return null;
		}
		int len = files.length;
		if (off >= len) {
			return new LocalFileImpl[0];
		}
		//sort by name only
		Arrays.sort(files, new Comparator<java.io.File>() {
			public int compare(java.io.File f1, java.io.File f2) {
				return f1.getName().compareTo(f2.getName());
			}
			
		});
		len = Math.min(len, off + max);
		IFile[] rl = new IFile[len - off];
		for (int i = off; i < len; i++) {
			rl[i - off] = new LocalFileImpl(files[i]);
		}
		return rl;
	}

	@Override
	public IFile[] listFiles(FileFilter filter) {
		java.io.File[] files = this.file.listFiles(filter);
		if (files == null) {
			return null;
		}
		IFile[] rl = new IFile[files.length];
		for (int i = 0; i < files.length; i++) {
			rl[i] = new LocalFileImpl(files[i]);
		}
		return rl;
	}

	@Override
	public IFile[] listFiles(FilenameFilter filter) {
		java.io.File[] files = this.file.listFiles(filter);
		if (files == null) {
			return null;
		}
		IFile[] rl = new IFile[files.length];
		for (int i = 0; i < files.length; i++) {
			rl[i] = new LocalFileImpl(files[i]);
		}
		return rl;
	}

	public boolean mkdir() {
		return this.file.mkdir();
	}

	public boolean move(URI dest) {
		if (dest.getScheme().equalsIgnoreCase("file")) {
			return this.file.renameTo(new java.io.File(dest));
		}
		//
		return false;
	}

	public boolean setAttribute(String name, Object value) {
		return false;
	}

	public boolean setContent(String s) {
		try {
			java.io.FileWriter out = new java.io.FileWriter(this.file);
			out.write(s);
			out.close();
			return true;
		} catch (Exception e) {
			debug(e);
		}
		return false;
	}

	public boolean setContentEncoding(String encoding) {
		return false;
	}

	public boolean setContentType(String mimeType) {
		return false;
	}

	public boolean setInputStream(InputStream in) {
		try {
			OutputStream out = new java.io.FileOutputStream(this.file);
			byte buf[] = new byte[File.BUFSIZE];
			int len;
			while ((len = in.read(buf, 0, File.BUFSIZE)) != -1) {
				out.write(buf, 0, len);
			}
			in.close();
			out.close();
			return true;
		} catch (Exception e) {
			debug(e);
		}
		return false;
	}

	public boolean setLastModified(long time) {
		return this.file.setLastModified(time);
	}

	public boolean setLength(long len) {
		return false;
	}

	public boolean setOutputStream(OutputStream out) {
		try {
			java.io.InputStream in = new java.io.FileInputStream(this.file);
			byte buf[] = new byte[File.BUFSIZE];
			int len;
			while ((len = in.read(buf, 0, File.BUFSIZE)) != -1) {
				out.write(buf, 0, len);
			}
			in.close();
			out.close();
			return true;
		} catch (Exception e) {
			debug(e);
		}
		return false;
	}

	@Override
	public String getName() {
		return this.file.getName();
	}

	public void deleteOnExit() {
		this.file.deleteOnExit();
	}

	@Override
	public URI toRealURI() {
		return this.file.toURI();
	}
}
